#include "TopHat.h"
#include "MorphologyOpen.h"
#include "MorphologyClose.h"
#include "AlgebraicDifference.h"



TopHat::TopHat () : _se (QSize (3, 3))
{

}

Ptr< QImage > TopHat::process (Ptr< QImage > pSrcImage)
{
	if (_type == WTT)
		return doWTT (pSrcImage);
	else
		return doBTT (pSrcImage);
}

void TopHat::setType (Type t)
{
	_type = t;
}

TopHat::Type TopHat::getType () const
{
	return _type;
}

Ptr< QImage > TopHat::doWTT (Ptr< QImage > pSrcImage)
{
	Ptr< QImage > pTempImage = MorphologyOpen (_se).operate (pSrcImage);
	Ptr< QImage > pProcessResult = AlgebraicDifference ().process (
			pSrcImage, pTempImage,
			pSrcImage->rect (), pTempImage->rect (), 
			QPoint (), QPoint (), pSrcImage->size ());
	int maxVal = 0;
	for (int v = 0; v < pProcessResult->height (); ++v) {
		QRgb * resultLine = (QRgb *)pProcessResult->scanLine (v);
		for (int u = 0; u < pProcessResult->width ();++u) {
			int resultR = qRed (resultLine[u]);
			if (resultR > maxVal) maxVal = resultR;
			int resultG = qGreen (resultLine[u]);
			if (resultG > maxVal) maxVal = resultR;
			int resultB = qBlue (resultLine[u]);
			if (resultB > maxVal) maxVal = resultR;
		}
	}
	float scale = 255.0 / maxVal;
	for (int v = 0; v < pProcessResult->height (); ++v) {
		QRgb * resultLine = (QRgb *)pProcessResult->scanLine (v);
		for (int u = 0; u < pProcessResult->width ();++u) {
			int resultR = scale * qRed (resultLine[u]);
			int resultG = scale * qGreen (resultLine[u]);
			int resultB = scale * qBlue (resultLine[u]);
			int resultA = qAlpha (resultLine[u]);
			resultLine[u] = qRgba (resultR, resultG, resultB, resultA);
		}
	}
	return pProcessResult;
}

Ptr< QImage > TopHat::doBTT (Ptr< QImage > pSrcImage)
{
	Ptr< QImage > pTempImage = MorphologyClose (_se).operate (pSrcImage);
	Ptr< QImage > pProcessResult = AlgebraicDifference ().process (pTempImage, pSrcImage,
			pTempImage->rect (), pSrcImage->rect (), 
			QPoint (), QPoint (), pSrcImage->size ());
	int maxVal = 0;
	for (int v = 0; v < pProcessResult->height (); ++v) {
		QRgb * resultLine = (QRgb *)pProcessResult->scanLine (v);
		for (int u = 0; u < pProcessResult->width ();++u) {
			int resultR = qRed (resultLine[u]);
			if (resultR > maxVal) maxVal = resultR;
			int resultG = qGreen (resultLine[u]);
			if (resultG > maxVal) maxVal = resultR;
			int resultB = qBlue (resultLine[u]);
			if (resultB > maxVal) maxVal = resultR;
		}
	}
	float scale = 255.0 / maxVal;
	for (int v = 0; v < pProcessResult->height (); ++v) {
		QRgb * resultLine = (QRgb *)pProcessResult->scanLine (v);
		for (int u = 0; u < pProcessResult->width ();++u) {
			int resultR = scale * qRed (resultLine[u]);
			int resultG = scale * qGreen (resultLine[u]);
			int resultB = scale * qBlue (resultLine[u]);
			int resultA = qAlpha (resultLine[u]);
			resultLine[u] = qRgba (resultR, resultG, resultB, resultA);
		}
	}
	return pProcessResult;
}
